using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration; 

namespace MetadataBasedConfig.POCO
{
    #region Class ModelMapping
    internal static class ModelMapping
    {
        private const string EntityTablePrefix = "Tbl";
        private const string AcTablePrefix = "Ac";
        private const string XrefTablePrefix = "Xref";

        internal static readonly Lazy<IMappingStrategy> AddUnderscoresBetweenWordsThenToLowerMappingStrategy =
            new Lazy<IMappingStrategy>(() => new CompositeMappingStrategy
            {
                Strategies = new IMappingStrategy[]
                                                                      {
                                                                          new AddUnderscoresBetweenWordsMappingStrategy()
                                                                          ,
                                                                          new ToLowerMappingStrategy()
                                                                      }
            });

        internal static readonly Lazy<IMappingStrategy> EntityTableNameMappingStrategy =
            new Lazy<IMappingStrategy>(() => new CompositeMappingStrategy
            {
                Strategies = new List<IMappingStrategy>(new[]
                                                                                                 {
                                                                                                     new AddPrefixMappingStrategy
                                                                                                         (EntityTablePrefix)
                                                                                                     ,
                                                                                                     AddUnderscoresBetweenWordsThenToLowerMappingStrategy
                                                                                                         .Value
                                                                                                 })
            });

        internal static readonly Lazy<IMappingStrategy> AcEntityTableNameMappingStrategy =
            new Lazy<IMappingStrategy>(() => new CompositeMappingStrategy
            {
                Strategies = new List<IMappingStrategy>(new[]
                                                                                                 {
                                                                                                     new AddPrefixMappingStrategy
                                                                                                         (AcTablePrefix)
                                                                                                     ,
                                                                                                     EntityTableNameMappingStrategy.Value
                                                                                                 })
            });
    }
    #endregion

    #region Class ModelMapping<TModel>
    public abstract class ModelMapping<TModel> : EntityTypeConfiguration<TModel>
        where TModel : class
    {

        protected static readonly Lazy<IMappingStrategy> ColumnNameMappingStrategy =
            new Lazy<IMappingStrategy>(() => new CompositeMappingStrategy
            {
                Strategies = new List<IMappingStrategy>(new[]
                                                                                                 {
                                                                                                     new AddPrefixMappingStrategy
                                                                                                         (typeof (TModel
                                                                                                              ).Name),
                                                                                                     ModelMapping.AddUnderscoresBetweenWordsThenToLowerMappingStrategy
                                                                                                         .Value
                                                                                                 })
            });

        #region Ctors
        protected ModelMapping(IMappingStrategy tableNameMappingStrategy)
        {
            if (tableNameMappingStrategy != null)
            {
                ToTable(tableNameMappingStrategy.To(typeof(TModel).Name));
            }
        }

        protected ModelMapping()
            : this(null)
        {

        }
        #endregion
    }
    #endregion
}